using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using RoboTrocity;
using RoboTrocity.Code.ObjectStates;

namespace RoboTrocity {
    class MovableObject : GameObject {
        protected Vector2 velocity, maxSpeed;
        private bool applyGravity;
		private bool facingLeft = false;

        public MovableObject():this(Point.Zero){}

        public MovableObject(Point _position)
            : base(_position){
            stateList = new List<ObjectState>();
            maxSpeed = new Vector2(10, 30);
            velocity = Vector2.Zero;
            applyGravity = true;
        }

        /*public void addState(TEMPObjectState.StateType stateType, Sprite relatedSprite) {
			TEMPObjectState state;
            //first check to see that there isn't a state with the same type already in the list
            for (int i=0; i<stateList.Count; i++){
				state = stateList[i];
				if (state.Type == stateType) {
					state = new TEMPObjectState(stateType, relatedSprite);
                    return;                 
                }
            }
            stateList.Add(new TEMPObjectState(stateType, relatedSprite));
            if (stateList.Count == 1) {
				addState(TEMPObjectState.StateType.DELETE, relatedSprite);
                currentState = stateList[0]; 
             }
        }*/

		

        public virtual void updateState(float elapsed) {
            // to be overriden
        }

       /* public TEMPObjectState getStateType(TEMPObjectState.StateType type) {
            foreach (TEMPObjectState oState in stateList) {
                if (oState.Type == type) {
                    return oState;
                }
            }
            return null;
        }*/

		public void setVelocityX(int _velocityX) {
			velocity.X = _velocityX;
		}
		public void setVelocityY(int _velocityY) {
			velocity.Y = _velocityY;
		}

        public void applyForce(Vector2 force) {
            applyForce(force.X, force.Y);
        }

        public virtual void applyForce(float x, float y) {
			velocity.Y = Math.Min(MaxSpeed.Y, Math.Max(-maxSpeed.Y, velocity.Y + y));
            velocity.X = Math.Min(MaxSpeed.X, Math.Max(-maxSpeed.X, velocity.X + x));
		}

		public void switchDirections() {
			facingLeft = !facingLeft;
		}

		public override void Draw(SpriteBatch sBatch, Camera camera) {
			if (this.Bounds.Right >= camera.Bounds.Left && this.Bounds.Left <= camera.Bounds.Right) {
				//this.DispSprite.DrawFrame(sBatch, Position - camera.Origin, ObjectDepth, facingLeft);
				//this.DispSprite.DrawFrame(sBatch, new Rectangle(Position.X, Position.Y, Width, Height), ObjectDepth, FacingLeft);
				this.DispSprite.DrawFrame(sBatch,
						new Rectangle(Position.X - camera.Origin.X, Position.Y - camera.Origin.Y, Width, Height),
						ObjectDepth,
						FacingLeft);
			}
		}

		public override void Update(float timeElapsed) {
			updateState(timeElapsed);
			//apply gravity
			if (HasGravity) {
				applyForce(0, (Game.GRAVITY * timeElapsed));
				if (velocity.X > 0) 
					velocity.X-- ;
				else if (velocity.X < 0)
					 velocity.X++;
			}

			CurrentState.Update(timeElapsed);
			
			//Position += velocity;
			DispSprite.UpdateFrame(timeElapsed);
		}

		#region Fields
		public Vector2 Velocity {
            get { return velocity; }
            set { velocity = value; }
        }

        public bool HasGravity {
            get { return applyGravity; }
            set { applyGravity = value; }
        }

        public override Sprite DispSprite {
			get { return CurrentState.StateSprite; }
		}

		public List<ObjectState> States {
			get { return stateList; }
		}

		public override CollisionBox Bounds {
			get { return new CollisionBox((int)(Position.X + Velocity.X), (int)(Position.Y + Velocity.Y),
										  Width, Height); }
		}

		public override float ObjectDepth {
			get { return 0.5f; }
		}

		public virtual Vector2 MaxSpeed {
			get { return maxSpeed; }
			set { maxSpeed = value; }
		}

		public bool FacingLeft {
			get { return facingLeft; }
			set { facingLeft = value; }
		}
		#endregion


	}
}


/* per-pixel collision code. Doubt we'll need it. 
	   * public bool intersectsWith(GameObject a) {
            //Code used from http://www.ziggyware.com/readarticle.php?article_id=48
            if (CollisionHandler.Intersects(this, a)){
			//	return true; //maybe use the rest of this for slopes?
                uint[] bitsA = new uint[a.DispSprite.Texture.Width * a.DispSprite.Texture.Height];
                a.DispSprite.Texture.GetData<uint>(bitsA);

                uint[] bitsB = new uint[this.DispSprite.Texture.Width * this.DispSprite.Texture.Height];
                this.DispSprite.Texture.GetData<uint>(bitsB);

                int x1 = Math.Max(a.Bounds.X, this.Bounds.X);
                int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, this.Bounds.X + this.Bounds.Width);

                int y1 = Math.Max(a.Bounds.Y, this.Bounds.Y);
                int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, this.Bounds.Y + this.Bounds.Height);

                for (int y = y1; y < y2; ++y) {
                    for (int x = x1; x < x2; ++x) {
                        if (((bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y) * a.DispSprite.Texture.Width] & 0xFF000000) >> 24) > 20 &&
                            ((bitsB[(x - this.Bounds.X) + (y - this.Bounds.Y) * this.DispSprite.Texture.Width] & 0xFF000000) >> 24) > 20)
                            return true;
                    }
                }
            }

            return false;
        }*/

